# -*- coding: utf-8 -*-            
# @Time    : 2025/5/19 8:24
# @FileName: web_app.py
# @Software: PyCharm
import yk_model
from flask import Flask,request,render_template
from keras.src.utils import load_img,img_to_array

x = yk_model.x_train
model = yk_model.Lenet5()
model.build(x.shape)
model.load_weights('yk_model.weights.h5')


app = Flask(__name__)

def read_image(path):
    img = load_img(path,target_size=x.shape)
    img = img_to_array(img)
    return img

# 2.
# Web应用的搭建功能性约束
# 1)    首页显示
# 应用程序在根URL（ / ）上提供了一个HTML页面（home.html），用户可以在此页面上找到上传图像的选项和说明。
@app.route('/')
def home():
    return render_template('home.html')
# 2)    图片上传与保存
# 用户可以通过Web界面上传图片文件。
# 上传的文件被保存在服务器的static / images目录下。
# 文件上传功能仅支持POST请求。
# 3)    图片预处理
# 上传的图片将被转换为灰度图像，并调整尺寸为28x28像素，这是LeNet - 5
# 模型所期望的输入尺寸。
# 图片数据被归一化到[0, 1]
# 范围内，这是神经网络模型常见的预处理步骤。
# 4)    模型加载与预测
# 在应用程序启动时，会加载一个预训练的LeNet - 5
# 模型，该模型已保存在model.h5文件中。
# 当用户上传图片后，应用程序会使用加载的模型对图片进行分类预测。
# 预测结果是通过找到模型输出中最大概率值的索引来确定的，这个索引对应于CIFAR - 10
# 数据集中的一个类别。
# 5)    结果展示
# 预测结果将被映射到具体的类别名称，如飞机、汽车、鸟等，这些类别名称与CIFAR - 10
# 数据集相对应。
# 用户将通过Web界面看到预测结果和他们上传的图片。
# 6)    错误处理
# 如果在文件上传、读取或预测过程中发生异常，应用程序将返回一个错误消息，提示用户检查文件扩展名是否正确。
@app.route('/predict', methods=['POST'])
def predict():
    try:
        if request.method == 'POST':
            file = request.files.get('file')
            filename = file.filename
            path = f'static/{filename}'
            file.save(path)
            img = read_image(path)
            product = model.predict(img).argmax()
            # 5.数据字段以及数据情况说明
            cifar10_labels = {
                0: 'airplane（飞机）',
                1: 'automobile（汽车）',
                2: 'bird（鸟）',
                3: 'cat（猫）',
                4: 'deer（鹿）',
                5: 'dog（狗）',
                6: 'frog（青蛙）',
                7: 'horse（马）',
                8: 'ship（船）',
                9: 'truck（卡车）'
            }
            return render_template('predict.html',
                                   user_image=path,
                                   product=cifar10_labels[product])
        else:
            return render_template('predict.html')
    except Exception as e:
        return str(e)

# 7)    服务配置与启动
# Flask应用程序配置为在调试模式下运行，这有助于开发过程中的错误追踪。
# 应用程序监听所有IP地址（0.0.0.0）的6008端口。
if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0',port=6008)